/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2003-2008 Intel Corporation. All Rights Reserved.
//
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_DV_VIDEO_DECODER)

#ifndef __UMC_DV_DECODER_H
#define __UMC_DV_DECODER_H

#include "ippdefs.h"
#include "umc_video_decoder.h"
#include "vm_thread.h"

// DV / DV50 have two functions for inverse quantization: ippiQuantInv_DV_16s_C1I and
// ippiQuantWeightBlockInv_DV_16s_C1I. First function ippiQuantInv_DV_16s_C1I is fast
// but the second function provides better accuracy of quantization.
// You can choose speed or quality (fast or exact type of realization)
// By default set FAST_DV.
// You can comment define and get better quality of DV/DV50 decoding.
#define FAST_DV

namespace UMC
{


class STORE_DV_SEGMENT_INFO;
class THREAD_ID;

class DVVideoDecoder : public VideoDecoder
{
public:
    // Default constructor
    DVVideoDecoder();
    // Destructor
    ~DVVideoDecoder();

    // Initialize DV decoder
    virtual Status    Init            (BaseCodecParams *init);

    // Close decoder
    virtual Status    Close           ();

    // Decode next frame
    virtual Status    GetFrame        (MediaData *pInData, MediaData *pOutData);

    // Get video stream information, valid after initialization
    virtual Status    GetInfo         (BaseCodecParams* info);

    // Get decoder performance
    virtual Status    GetPerformance  (Ipp64f *perf);

    // Reset decoder into initial state
    virtual Status    Reset           ();

    // reset skip frame counter
    virtual Status    ResetSkipCount  (){return UMC_ERR_NOT_IMPLEMENTED;};

    // increment skip frame counter
    virtual Status    SkipVideoFrame  (Ipp32s){return UMC_ERR_NOT_IMPLEMENTED;};

    // get skip frame counter statistic
    virtual Ipp32u    GetNumOfSkippedFrames  (){return 0;};

protected:
    friend class DV100VideoDecoder;

    // Decode DC only
    void HuffmanDecodeSegment_DV_DC_only(Ipp8u *lpbSource, Ipp16u *lpsDest);

    // Decompress DV segment
    virtual void DecompressSegment(Ipp32u nThreadNum);

    // initialize DV dequantize table
    Ipp32s DVCreateADequantizeTable        ();

    // Select function 'StoreDVSegment'
    virtual void SelectStoreFunction(void *pSource);

    // Function for processing incorrect params in GetFrame method
    virtual void CheckSetCorrectParams(int byteDSF);

    // Fill correspond dest & source pointers
    void InitializeStoreDVSDInfo(STORE_DV_SEGMENT_INFO &PasteInfo, Ipp32u i, Ipp32u k, Ipp32u ThreadNum);
    void InitializeStoreDV25Info(STORE_DV_SEGMENT_INFO &PasteInfo, Ipp32u i, Ipp32u k, Ipp32u ThreadNum);

    // Store uncompressed DV segment
    void StoreDVSDSegment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDVSDSegment_2s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDVSDSegment_4s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDVSDSegment_8s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDV25Segment(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDV25Segment_2s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDV25Segment_4s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);
    void StoreDV25Segment_8s(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);

    void (DVVideoDecoder::*StoreDVSegment)(Ipp32u i, Ipp32u k, Ipp32u nThreadNum);    // (void (*)(Ipp32u, Ipp32u, Ipp32u) pointer to store function

    Ipp32u m_nMaxNumberOfDIFSequences;                        // (Ipp32u) maximum number of DIF sequences

    static Ipp32s         dvTable1[];                         // DV decoding table one
    static Ipp32s         dvTable2[];                         // DV decoding table two
    static Ipp32u         _INTERNAL_DEZIGZAG_TABLE_0[] ;      // zigzag table

    Ipp16u                **m_ppShortBlocks;                  // (Ipp16u **) pointer to array of pointers to working data
    MemID                 m_DCTBlocksBufferMID;
    Ipp32u                *m_pHuffTable;                      // pointer to huffman table
    Ipp16u                *m_lpADequantizeTable;              // pointer to dequantize table
    MemID                 m_DequantizeTableMID;
    Ipp32u                *m_lpADequantizeLineTable;          // pointer to line dequantize table
    MemID                 m_InternalFrameBufferMID;
    Ipp8u                 *m_lpvInternalFrameBuffer;          // aligned internal frame buffer

    Ipp8u                 *m_lpDestination;                   // (Ipp8u *) pointer to destination buffer
    Ipp8u                 *m_lpSource;                        // (Ipp8u *) pointer to compressed frame

    Ipp32u                m_nSystem;                          // (Ipp32u) frame system type
    Ipp32u                m_nSourceFrameSize;                 // size of source frame
    bool                  m_bDCOnly;                          // decode only DC

    bool                  m_bInitSuccess;                     // True, if Init() success

    Ipp32s                m_nWidth;                           // width
    Ipp32s                m_nHeight;                          // height
    Ipp32s                m_nPitch;                           // pitch
    Ipp32s                m_lSizeSubSampled;                  // resampling ratio

    Ipp32u m_nNumberOfThreads;                                // (Ipp32u) number of threads
    vm_event m_Quit;                                          // (vm_event) event to quit
    vm_thread *m_lpThreads;                                   // (vm_thread *) pointer to array of thread(s)
    vm_event *m_lpStartEvent;                                 // (vm_event *) pointer to array of event(s)
    vm_event *m_lpStopEvent;                                  // (vm_event *) pointer to array of event(s)
    THREAD_ID *m_lpThreadsID;                                 // (THREAD_ID *) pointer to array of thread's ID

    // Additional thread working routine
    static Ipp32u VM_THREAD_CALLCONVENTION ThreadWorkingRoutine(void *lpv);
};

} // end namespace UMC

#endif // __UMC_DV_DECODER_H

#endif //(UMC_ENABLE_DV_VIDEO_DECODER)
